/*
 ------------------------------------------------------------------------------
 Copyright (C) 2006-2007 Team Blur.

 This file is part of the Quantum Engine source code.

 The Quantum Engine source code is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your
 option) any later version.

 The Quantum Engine source code is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 more details.

 You should have received a copy of the GNU General Public License along with
 the Quantum Engine source code; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 ------------------------------------------------------------------------------
*/


#ifndef __CM_LOCAL_H__
#define __CM_LOCAL_H__


#include "../core/core_main.h"
#include "cm_public.h"


#define MAX_CLIP_MODELS					2048

// To allow bounding boxes to be treated as inline models, we allocate some
// extra indices along with those needed by the map
#define BOX_MODEL_MATERIALS				1
#define BOX_MODEL_PLANES				6
#define BOX_MODEL_BRUSHSIDES			6
#define BOX_MODEL_BRUSHES				1

typedef struct {
	char					name[MAX_OSPATH];

	int						surfaceFlags;
	int						contentFlags;
} cmMaterial_t;

typedef struct {
	cmMaterial_t *			material;

	odPlane *				plane;
} cmBrushSide_t;

typedef struct {
	cmMaterial_t *			material;

	odBounds				bounds;

	int						numSides;
	cmBrushSide_t *			sides;

	int						contentsCount;		// To avoid repeated testings
	int						traceCount;			// To avoid repeated testings
} cmBrush_t;

typedef struct {
	int						facetPlane;

	int						numBorders;			// 3 or 4 + 6 axial bevels + 3 or 4 * 4 edge bevels
	int						borderInward;		// Bit vector
	short					borderPlanes[26];
} cmSurfaceFacet_t;

typedef struct {
	surfaceType_t			type;

	cmMaterial_t *			material;

	odBounds				bounds;

	odPlane					sides[6];

	int						numPlanes;
	odPlane *				planes;

	int						numFacets;
	cmSurfaceFacet_t *		facets;

	int						contentsCount;		// To avoid repeated testings
	int						traceCount;			// To avoid repeated testings
} cmSurface_t;

typedef struct {
	int						cluster;
	int						area;

	bool					canSeePortalSky;

	int						contentFlags;		// OR'ed content flags from all brushes and surfaces

	int						numLeafBrushes;
	int						firstLeafBrush;

	int						numLeafSurfaces;
	int						firstLeafSurface;
} cmLeaf_t;

typedef struct {
	odPlane *				plane;

	int						children[2];		// Negative numbers are leafs, not nodes
} cmNode_t;

typedef struct {
	odBounds				bounds;

	odPlane					sides[6];

	cmLeaf_t				leaf;
} cmInlineModel_t;

typedef struct {
	int						portalNum;
	int						areas[2];

	bool					open;
} cmPortal_t;

typedef struct {
	int						numAreaPortals;
	int						firstAreaPortal;

	int						floodNum;
	int						floodCount;
} cmArea_t;

typedef struct {
	bool					loaded;
	char					name[MAX_OSPATH];
	int						size;

	int						contentsCount;		// To avoid repeated testings
	int						traceCount;			// To avoid repeated testings
	int						floodCount;			// For area flooding

	int						numMaterials;
	cmMaterial_t *			materials;

	int						numPlanes;
	odPlane *				planes;

	int						numBrushSides;
	cmBrushSide_t *			brushSides;

	int						numBrushes;
	cmBrush_t *				brushes;

	int						numSurfacePlanes;
	odPlane *				surfacePlanes;

	int						numSurfaceFacets;
	cmSurfaceFacet_t *		surfaceFacets;

	int						numSurfaces;
	cmSurface_t **			surfaces;			// Surfaces with no collision data will be NULL

	int						numLeafBrushes;
	int *					leafBrushes;

	int						numLeafSurfaces;
	int *					leafSurfaces;

	int						numLeafs;
	cmLeaf_t *				leafs;

	int						numNodes;
	cmNode_t *				nodes;

	int						numInlineModels;
	cmInlineModel_t *		inlineModels;

	int						numClusters;
	int						clusterBytes;
	byte *					pvs;
	byte *					noPVS;

	int						numPortals;
	cmPortal_t *			portals;

	int						numAreaPortals;
	int *					areaPortals;

	int						numAreas;
	cmArea_t *				areas;
} clipMap_t;

typedef struct {
	int						contentFlags;		// OR'ed content flags from all surfaces

	odBounds				bounds;

	odPlane					sides[6];

	int						numSurfaces;
	cmSurface_t *			surfaces;
} cmStaticModel_t;

typedef struct {
	int						parent;				// Parent index

	odJointMat				matrix;
} cmJoint_t;

typedef struct {
	odVec3					baseXyz;

	int						firstWeight;
	int						numWeights;
} cmVertex_t;

typedef struct {
	int						joint;				// Joint index
	float					jointWeight;

	odVec3					offset;
} cmWeight_t;

typedef struct {
	cmMaterial_t *			material;

	odBounds				bounds;

	odPlane					sides[6];

	int						numIndices;
	int *					indices;

	int						numVertices;
	cmVertex_t *			vertices;

	int						numWeights;
	cmWeight_t *			weights;

	// Computed when instanced
	odVec3 *				transformedXyz;

	int						numTriangles;
	odPlane *				facePlanes;
	odPlane *				edgePlanes;
} cmTriangleSurface_t;

typedef struct {
	int						contentFlags;		// OR'ed content flags from all surfaces

	odBounds				bounds;

	odPlane					sides[6];

	int						numJoints;
	cmJoint_t *				joints;

	int						numSurfaces;
	cmTriangleSurface_t *	surfaces;
} cmDynamicModel_t;

typedef enum {
	CLIP_MODEL_BAD,
	CLIP_MODEL_INLINE,
	CLIP_MODEL_STATIC,
	CLIP_MODEL_DYNAMIC
} clipModelType_t;

typedef struct clipModel_s {
	char					name[MAX_OSPATH];
	clipModelType_t			type;

	void *					data;
	int						size;

	struct clipModel_s *	nextHash;
} clipModel_t;

typedef struct {
	int						contents;
	int						leafContents;
	int						brushContents;
	int						patchContents;
	int						trisoupContents;
	int						meshContents;

	int						traces;
	int						leafTraces;
	int						brushTraces;
	int						patchTraces;
	int						trisoupTraces;
	int						meshTraces;

	int						tests;
	int						leafTests;
	int						brushTests;
	int						patchTests;
	int						trisoupTests;
	int						meshTests;

	int						leafPoints;

	int						pvsPoints;
	int						pvsBounds;

	int						areaPoints;
	int						areaBounds;
} cmStats_t;

extern clipMap_t			cm;

extern cmStats_t			cm_stats;

extern cvar_t *				cm_skipSurfaces;
extern cvar_t *				cm_skipModels;
extern cvar_t *				cm_skipPVS;
extern cvar_t *				cm_skipAreas;
extern cvar_t *				cm_showStats;

void				CM_FloodAreaConnections (void);

void				CM_LoadInlineModel (int index, void *data);

void				CM_InitBoxModel (void);

void				CM_FreeModels (void);

void				CM_InitModels (void);
void				CM_ShutdownModels (void);


#endif	// __CM_LOCAL_H__
